/*
 * With gdbus
 */
#include <stdio.h>
#include <stdlib.h>
#include <glib.h>
#include <gio/gio.h>
#include "common.h"

static void on_sms_incoming(GDBusConnection *conn, const gchar *sender_name, const gchar *object_path,
        const gchar *interface_name, const gchar *signal_name, GVariant *parameters, gpointer user_data) {
    if (conn == NULL) {
        g_print("fuck, connection is NULL\n");
        return;
    }
    g_print("sender name %s\n", sender_name);
    g_print("object path %s\n", object_path);
    g_print("interface_name %s\n", interface_name);
    g_print("signal name %s\n", signal_name);
    g_print("user data 0x%0x\n", (unsigned int) user_data);
    g_print("type of parameters is '%s'\n", g_variant_get_type(parameters));
    /* retrieve message from returned parameters */
    const gchar *message = NULL;
    g_print("number of children is '%d'\n", g_variant_n_children(parameters));
    GVariant *msg = g_variant_get_child_value(parameters, 0);
    gsize length = 0;
    message = g_variant_get_string(msg, &length);
    g_print("message is '%s', with len %d\n", message, length);

    /* retrieve other properties of this message, directly with lookup*/
    GVariant *props = g_variant_get_child_value(parameters, 1);
    if (props == NULL) {
        g_print("not property\n");
        return;
    }
    g_print("props type info '%s'\n", g_variant_get_type(props));
    const gchar *local_sent_time = NULL;
    const gchar *sent_time = NULL;
    const gchar *sender = NULL;
    if (!g_variant_lookup(props, "LocalSentTime", "&s", &local_sent_time)) {
        g_print("fuck no local_sent_time\n");
    } else {
        g_print("local sent time is '%s'\n", local_sent_time);
    }
    if (!g_variant_lookup(props, "SentTime", "&s", &sent_time)) {
        g_print("no sent time\n");
    } else {
        g_print("sent time is '%s'\n", sent_time);
    }
    if (!g_variant_lookup(props, "Sender", "&s", &sender)) {
        g_print("sender is not present\n");
    } else {
        g_print("sender is '%s'\n", sender);
    }

    /* iterating the dictionary */
    g_print("with iter loop:\n");
    iterate_dictionary(props);
}

static void on_property_changed(GDBusConnection *conn, const gchar *sender_name,
        const gchar *object_path, const gchar *interface_name, const gchar *signal_name,
        GVariant *parameters, gpointer user_data) {
    g_print("on_property_changed are you aware of that\n");
    //g_print("type of parameters '%s'\n", g_variant_get_type_string(parameters));
    GVariant *key = g_variant_get_child_value(parameters, 0);
    gsize length = 0;
    const gchar *key_value = g_variant_get_string(key, &length);
    GVariant *value_box = g_variant_get_child_value(parameters, 1);
    GVariant *value = g_variant_get_variant(value_box);
    const gchar *value_type = g_variant_get_type_string(value);
    //g_print("value type is '%s'\n", value_type);
    const gchar *value_value;
    if (g_strcmp0(value_type, "s") == 0) {
        value_value = g_variant_get_string(value, &length);
    } else if (g_strcmp0(value_type, "b") == 0) {
        gboolean b = g_variant_get_boolean(value);
        value_value = b ? g_strdup("1 (TRUE)") : g_strdup("0 (FALSE)");
    } else {
        g_print("error: unsupported type '%s'\n", value_type);
    }
    g_print("\tproperty '%s' has value '%s'\n", key_value, value_value);
    //g_free(key_value);
    //g_free(value_value);
    //g_variant_unref(key);
    //g_variant_unref(value_box);
}

static void on_message_added(GDBusConnection *conn, const gchar *sender_name,
        const gchar *object_path, const gchar *interface_name, const gchar *signal_name,
        GVariant *parameters, gpointer user_data) {
    g_print("on_message_added are you aware of that\n");
    //g_print("type of parameters '%s'\n", g_variant_get_type_string(parameters));
    GVariant *path = g_variant_get_child_value(parameters, 0);
    const gchar *opath;
    g_variant_get(path, "o", &opath);
    g_print("message [%s] is added to ofono queue\n", opath);
    g_free(opath);
    g_variant_unref(path);
    GVariant *info = g_variant_get_child_value(parameters, 1);
    iterate_dictionary(info);
    g_variant_unref(info);
}

static void on_message_removed(GDBusConnection *conn, const gchar *sender_name,
        const gchar *object_path, const gchar *interface_name, const gchar *signal_name,
        GVariant *parameters, gpointer user_data) {
    g_print("on_message_removed are you aware of that\n");
    //g_print("type of parameters '%s'\n", g_variant_get_type_string(parameters));
    const gchar *path;
    g_variant_get(parameters, "(o)", &path);
    g_print("message [%s] is removed from ofono queue\n", path);
    g_free(path);
}

int main(int argc, char **argv) {
    g_type_init();
    gpointer callback_data;
    const gchar *modems[MODEM_COUNT_LIMIT];
    gsize modem_count = 0;
    get_modem_paths(modems, &modem_count);
    if (modem_count < 1) {
        g_print("there are no modem available\n");
        return -1;
    }
    GMainLoop *main_loop = g_main_loop_new(NULL, FALSE);
    GDBusConnection *conn = get_system_bus_connection();
    guint identity = g_dbus_connection_signal_subscribe(conn,
            OFONO_SERVICE_NAME, OFONO_MESSAGE_MANAGER, "IncomingMessage",
            modems[0], NULL, G_DBUS_SIGNAL_FLAGS_NONE, on_sms_incoming, NULL, NULL);

    identity = g_dbus_connection_signal_subscribe(conn,
            OFONO_SERVICE_NAME, OFONO_MESSAGE_MANAGER, "ImmediateMessage",
            modems[0], NULL, G_DBUS_SIGNAL_FLAGS_NONE, on_sms_incoming, NULL, NULL);

    identity = g_dbus_connection_signal_subscribe(conn,
            OFONO_SERVICE_NAME, OFONO_MESSAGE_MANAGER, "PropertyChanged",
            modems[0], NULL, G_DBUS_SIGNAL_FLAGS_NONE, on_property_changed, NULL, NULL);

    identity = g_dbus_connection_signal_subscribe(conn,
            OFONO_SERVICE_NAME, OFONO_MESSAGE_MANAGER, "MessageAdded",
            modems[0], NULL, G_DBUS_SIGNAL_FLAGS_NONE, on_message_added, NULL, NULL);

    identity = g_dbus_connection_signal_subscribe(conn,
            OFONO_SERVICE_NAME, OFONO_MESSAGE_MANAGER, "MessageRemoved",
            modems[0], NULL, G_DBUS_SIGNAL_FLAGS_NONE, on_message_removed, NULL, NULL);
    g_main_loop_run(main_loop);
    for (int i = 0; i < modem_count; i++) {
        g_free(modems[i]);
    }
    return 0;
}
